import React from 'react';
import ReactDOM from 'react-dom';

/* 
 * 函数式组件（函数返回JSX元素）：Clock时钟组件 
 *   =>调取组件可以是单闭合，也可以是双闭合（双闭合调用可以把子元素当做属性中的children传递给组件，类似于vue中的slot）
 *   =>底层运作的时候，如果虚拟DOM对象的type是一个函数（或者一个类），首先会把函数执行（把解析出来的props传递给这个函数），函数会把一个新的虚拟DOM对象返回，最后整体渲染
 *   =>React.Children提供对应的方法专门用来处理传递进来的子元素children的
 *   =>传递进来的属性是只读的（只能获取，但是不能直接修改其里面的值），如果非要修改某一个值，可以把其赋值给一个变量（状态）再去修改变量（状态）；再或者把属性深克隆出来一份，供调取和修改；
 * 
 * 函数式组件属于静态组件，调取组件渲染出一个结果，后续除非重新渲染组件，否则第一次渲染的内容不会改变（当然REACT HOOKS可以帮我们解决这个问题）
 */
// function Clock(props) {
// 	let index = props.index;
// 	index = 1000;

// 	let FOOT = null,
// 		HEAD = null;
// 	React.Children.forEach(props.children, item => {
// 		let name = item.props.name;
// 		if (name === "HEAD") {
// 			HEAD = item;
// 		}
// 		if (name === "FOOT") {
// 			FOOT = item;
// 		}
// 	});
// 	/* let children = props.children,
// 		FOOT = null,
// 		HEAD = null;
// 	if (children) {
// 		if (!Array.isArray(children)) {
// 			children = [children];
// 		}
// 		HEAD = children.find(item => item.props.name === 'HEAD');
// 		FOOT = children.find(item => item.props.name === 'FOOT');
// 	} */

// 	return <div className={props.className} style={props.style}>
// 		{HEAD}
// 		<br />
// 		{new Date().toLocaleString()}
// 		<br />
// 		{FOOT}
// 		<br />
// 		{index}
// 	</div>;
// }

// ReactDOM.render(<>
// 	<Clock index={1} className="text" style={{ color: 'red' }}>
// 		<span name="FOOT">哈哈哈哈</span>
// 		<span name="HEAD">珠峰培训</span>
// 	</Clock>
// </>, document.getElementById('root'));

/*
 * 类组件：创建一个类继承React.Component/React.PureComponent
 *   =>渲染的时候的发现type是一个类，则会创建当前类的实例
 *   =>同样会把解析出来的props传递给当前这个类，并且REACT会帮我们把props挂载到当前类的实例上（this.props即可操作属性），但是默认情况下是执行完constructor才把props挂载到实例上的，所以在constructor中无法基于this.props获取
 * 
 * 受控组件：基于数据驱动视图的渲染（类组件也是动态组件）
 *    =>组件状态
 * 非受控组件：直接操作DOM的
 *    =>ref
 */
/* class Clock extends React.Component {
	constructor(props) {
		super(props); //=>类似于CALL继承 React.Component.call(this,props)  =>this.props=props
	}
	render() {
		let time = new Date().toLocaleString();
		return <div>
			{time}
		</div>;
	}
} */

class Clock extends React.Component {
	constructor(props) {
		super(props);
		// 初始化状态（把后续需要用到的状态初始化）
		this.state = {
			time: new Date().toLocaleString()
		};
	}
	render() {
		// 在渲染的时候使用状态
		return <div>
			{this.state.time}
			<br />
			{/* <button onClick={this.handle}>暂停运动</button> */}
			{/* <button onClick={ev => {
				// clearInterval(this.autoTimer);
				this.handle(ev, 100);
			}}>暂停运动</button> */}
			{/* <button onClick={this.handle.bind(this, 100)}>暂停运动</button> */}

			{/* <button ref="btn">暂停运动</button> */}
			<button ref={x => {
				//真实项目中ref经常这样玩：写成函数表达式
				// x=>当前操作的元素
				this.btn = x; //=>直接把元素挂载到实例上，不走refs
			}}>暂停运动</button>
		</div>;
	}
	// 编写操作方法：写在类原型上的，直接基于this.xxx即可调用
	// =>给元素的事件绑定方法，默认方法中的this->undefined，真实项目中我们需要像vue一样保证方法中的this都是实例，这样方便我们的操作，此时我们需要把方法写成箭头函数（THIS是上下文中的实例）
	handle = (n, ev) => {
		console.log(ev, n);
		clearInterval(this.autoTimer);
	}
	// 第一次加载完成的生命周期函数
	componentDidMount() {
		this.autoTimer = setInterval(_ => {
			// 可以修改状态，但是不能控制视图重新渲染 => setState
			// this.state.time = new Date().toLocaleString();
			// setState(partialState, callback)：部分状态、当状态更新视图重新渲染完触发的回调函数（类似于vue中的$nextTick）
			this.setState({
				time: new Date().toLocaleString()
			});
		}, 1000);

		//=>可以获取到DOM元素
		//设置ref则这样获取
		// console.log(this.refs.btn);  
		this.btn.addEventListener('click', _ => {
			clearInterval(this.autoTimer);
		});
	}
}

ReactDOM.render(<>
	<Clock index={1} >
		<span>珠峰培训</span>
	</Clock>
</>, document.getElementById('root'));
